package cn.xny.service.impl;

import cn.xny.Mapper.HighlightResultMapper;
import cn.xny.dto.AggPageList;
import cn.xny.dto.BucketVo;
import cn.xny.dto.CourseParamsDto;
import cn.xny.repository.CourseDocRepository;
import cn.xny.service.ISearchService;
import cn.xny.txcc.dto.CourseEsDto;
import cn.xny.txcc.result.PageList;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;


import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;

import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;

import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class SearchServiceImpl implements ISearchService {

    @Autowired
    private CourseDocRepository courseDocRepository;
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    @Autowired
    private HighlightResultMapper highlightResultMapper;


    @Override
    public void save(CourseEsDto courseEsDto) {
   courseDocRepository.save(courseEsDto);
    }

    @Override
    //条件查询，分页查询，排序查询
    public PageList<CourseEsDto> searchCourse(CourseParamsDto courseParamsDto) {


           // 创建一个类的对象：1.构造方法2.工具类3.工厂模式
        NativeSearchQueryBuilder SearchQueryBuilder = new NativeSearchQueryBuilder();
        //1.添加分页条件
        SearchQueryBuilder.withPageable(PageRequest.of((courseParamsDto.getPage()-1)*courseParamsDto.getRows(),courseParamsDto.getRows()));
       //2.添加排序条件
        String orderFile = choseOrderFile(courseParamsDto.getSortField());
        SortOrder sortOrder = courseParamsDto.getSortType().equals("desc")?SortOrder.DESC:SortOrder.ASC;
        SearchQueryBuilder.withSort(SortBuilders.fieldSort(orderFile).order(sortOrder));
     //构建查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //3.1keyword查询条件
        if(StringUtils.hasLength(courseParamsDto.getKeyword())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("name",courseParamsDto.getKeyword()));

        }
        //查询是否收费
        if (StringUtils.hasLength(courseParamsDto.getChargeName())){

            boolQueryBuilder.filter(QueryBuilders.termQuery("chargeName",courseParamsDto.getChargeName()));

        }
        //课程分类查询
        if(courseParamsDto.getCourseTypeId()!=null){
            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId",courseParamsDto.getCourseTypeId()));

        }
        //课程等级
        if (  StringUtils.hasLength(courseParamsDto.getGradeName())){
            boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName",courseParamsDto.getGradeName()));
        }
        //按照区间
        if (courseParamsDto.getPriceMin()!=null){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(courseParamsDto.getPriceMin()));
        }
        if (courseParamsDto.getPriceMax()!=null){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(courseParamsDto.getPriceMax()));

        }
        SearchQueryBuilder.withQuery(boolQueryBuilder);
     //做高亮处理
        HighlightBuilder.Field  highlightField = new HighlightBuilder.Field("name")

                .preTags("<span style='color:pink'>")
                .postTags("</span>");

        SearchQueryBuilder.withHighlightFields(highlightField);
      //构建聚合查询
        TermsAggregationBuilder gradeName = AggregationBuilders.terms("gradeNameAgg").field("gradeName");
        TermsAggregationBuilder chargeName = AggregationBuilders.terms("chargeNameAgg").field("chargeName");
        SearchQueryBuilder.addAggregation(chargeName).addAggregation(gradeName);

        //构建最终查询对象
        NativeSearchQuery build = SearchQueryBuilder.build();
        AggregatedPage<CourseEsDto> search = elasticsearchRestTemplate.queryForPage(build, CourseEsDto.class, highlightResultMapper);
        //取出所有聚合查询对象的结果集,并转换成map
        Map<String, Aggregation> stringAggregationMap = search.getAggregations().asMap();

        Map<String,List<BucketVo>> map = new HashMap<>();
        stringAggregationMap.keySet().forEach(aggkey-> {
            //Map中的key值
            ParsedStringTerms aggregation  =   (ParsedStringTerms)stringAggregationMap.get(aggkey);
            //获取统计结果集
            List<? extends Terms.Bucket> buckets = aggregation.getBuckets();
            List<BucketVo> list = new ArrayList<>();
            for (Terms.Bucket bucket : buckets) {
                list.add(new BucketVo(bucket.getKey().toString(),bucket.getDocCount()));
            }
            //一组数据处理完放到map中
            map.put(aggkey,list);
        });

       //命中的总条数
        long totalElements = search.getTotalElements();
        List<CourseEsDto> content = search.getContent();

        return new AggPageList<>(totalElements,content,map);


    }

    public String choseOrderFile(String s){
        switch (s){

            case "xl": return "saleCount";
            case "xp": return "onlineTime";
            case "pl": return "commentCount";
            case "jg": return "price";
            case "rq": return "viewCount";

        }
        return "saleCount";

    }
}
